package ar.com.jsejtman.cajugastos2.core.entity;

import ar.com.jsejtman.common.domain.entity.Identifiable;
import java.math.BigDecimal;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Version;

/**
 * Representa un gasto.
 * 
 * @author jsejtman
 * 
 */
@Entity
@Table(name = "GASTOS")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "TIPO_DE_GASTO", discriminatorType = DiscriminatorType.STRING)
public abstract class Gasto implements Identifiable<Long> {

	/**
	 * identificador.
	 */
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "id")
	private Long id;

	/**
	 * Fecha.
	 */
	@Column(name = "FECHA", unique = false, nullable = false)
	private Date fecha;
	/**
	 * Descripcion.
	 */
	@Column(name = "DESCRIPCION", nullable = false)
	private String descripcion;
	/**
	 * frecuencia.
	 */
	@Column(name = "FRECUENCIA_ID", nullable = false)
	private Integer frecuenciaId;
	/**
	 * categoria.
	 */
	@ManyToOne
	@JoinColumn(name = "CATEGORIA_ID", nullable = false)
	private Categoria categoria;
	/**
	 * lugar.
	 */
	@ManyToOne
	@JoinColumn(name = "LUGAR_ID", nullable = false)
	private Lugar lugar;
	/**
	 * medio de pago.
	 */
	@ManyToOne
	@JoinColumn(name = "MEDIO_DE_PAGO_ID", nullable = true)
	private MedioDePago medioDePago;

	/**
	 * Versión de la entidad.
	 */
	@Column(name = "VERSION")
	@Version
	private Long version;

	/**
	 * Retorna el monto del gasto.
	 * 
	 * @return El monto
	 */
	abstract BigDecimal getMonto();

	/**
	 * Indica si es un gasto compuesto.
	 * 
	 * @return si es un gasto compuesto.
	 */
	public final Boolean isGastoCompuesto() {

		return this instanceof GastoCompuesto;
	}

	/**
	 * Indica si es un gasto simple.
	 * 
	 * @return si es un gasto simple.
	 */
	public final Boolean isGastoSimple() {

		return this instanceof GastoSimple;
	}

	/**
	 * Devuelve el valor de id.
	 * 
	 * @return El valor de id.
	 */
	public final Long getId() {

		return this.id;
	}

	/**
	 * Asigna un nuevo valor a id.
	 * 
	 * @param id El valor a asignar a id.
	 */
	public final void setId(final Long id) {

		this.id = id;
	}

	/**
	 * Devuelve el valor de fecha.
	 * 
	 * @return El valor de fecha.
	 */
	public final Date getFecha() {

		return this.fecha;
	}

	/**
	 * Asigna un nuevo valor a fecha.
	 * 
	 * @param fecha El valor a asignar a fecha.
	 */
	public final void setFecha(final Date fecha) {

		this.fecha = fecha;
	}

	/**
	 * Devuelve el valor de descripcion.
	 * 
	 * @return El valor de descripcion.
	 */
	public final String getDescripcion() {

		return this.descripcion;
	}

	/**
	 * Asigna un nuevo valor a descripcion.
	 * 
	 * @param descripcion El valor a asignar a descripcion.
	 */
	public final void setDescripcion(final String descripcion) {

		this.descripcion = descripcion;
	}

	/**
	 * Devuelve el valor de frecuencia.
	 * 
	 * @return El valor de frecuencia.
	 */
	public final Frecuencia getFrecuencia() {

		return Frecuencia.fromId(this.frecuenciaId);
	}

	/**
	 * Asigna un nuevo valor a frecuencia.
	 * 
	 * @param frecuencia El valor a asignar a frecuencia.
	 */
	public final void setFrecuencia(final Frecuencia frecuencia) {

		this.frecuenciaId = frecuencia.getId();
	}

	/**
	 * Devuelve el valor de categoria.
	 * 
	 * @return El valor de categoria.
	 */
	public final Categoria getCategoria() {

		return this.categoria;
	}

	/**
	 * Asigna un nuevo valor a categoria.
	 * 
	 * @param categoria El valor a asignar a categoria.
	 */
	public final void setCategoria(final Categoria categoria) {

		this.categoria = categoria;
	}

	/**
	 * Devuelve el valor de lugar.
	 * 
	 * @return El valor de lugar.
	 */
	public final Lugar getLugar() {

		return this.lugar;
	}

	/**
	 * Asigna un nuevo valor a lugar.
	 * 
	 * @param lugar El valor a asignar a lugar.
	 */
	public final void setLugar(final Lugar lugar) {

		this.lugar = lugar;
	}

	/**
	 * Devuelve el valor de medioDePago.
	 * 
	 * @return El valor de medioDePago.
	 */
	public final MedioDePago getMedioDePago() {

		return this.medioDePago;
	}

	/**
	 * Asigna un nuevo valor a medioDePago.
	 * 
	 * @param medioDePago El valor a asignar a medioDePago.
	 */
	public final void setMedioDePago(final MedioDePago medioDePago) {

		this.medioDePago = medioDePago;
	}

	/**
	 * Devuelve el valor de version.
	 * 
	 * @return El valor de version.
	 */
	public final Long getVersion() {

		return this.version;
	}

	/**
	 * Asigna un nuevo valor a version.
	 * 
	 * @param version El valor a asignar a version.
	 */
	public final void setVersion(final Long version) {

		this.version = version;
	}

}
